package com.zbkj.service.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.zbkj.common.constants.BalanceRecordConstants;
import com.zbkj.common.model.user.UserBalanceRecord;
import com.zbkj.common.page.CommonPage;
import com.zbkj.common.request.PageParamRequest;
import com.zbkj.common.request.UserBalanceSearchRequest;
import com.zbkj.common.response.UserBalancePageDataResponse;
import com.zbkj.common.utils.CrmebDateUtil;
import com.zbkj.common.utils.CrmebUtil;
import com.zbkj.common.vo.DateLimitUtilVo;
import com.zbkj.service.dao.UserBalanceRecordDao;
import com.zbkj.service.service.UserBalanceRecordService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.*;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
*  UserBalanceRecordServiceImpl 接口实现
 
*/
@Service
public class UserBalanceRecordServiceImpl extends ServiceImpl<UserBalanceRecordDao, UserBalanceRecord> implements UserBalanceRecordService {

    @Resource
    private UserBalanceRecordDao dao;

    /**
     * 获取用户消费记录
     */
    @Override
    public List<UserBalanceRecord> getMonetaryRecordByUid(Integer uid) {
        LambdaQueryWrapper<UserBalanceRecord> lqw = Wrappers.lambdaQuery();
        lqw.eq(UserBalanceRecord::getUid, uid);
        lqw.eq(UserBalanceRecord::getLinkType, BalanceRecordConstants.BALANCE_RECORD_LINK_TYPE_ORDER);
        lqw.eq(UserBalanceRecord::getType, BalanceRecordConstants.BALANCE_RECORD_TYPE_SUB);
        lqw.orderByDesc(UserBalanceRecord::getId);
        return dao.selectList(lqw);
    }

    /**
     * 获取用户充值记录
     */
    @Override
    public List<UserBalanceRecord> getRechargeRecordByUid(Integer uid) {
        LambdaQueryWrapper<UserBalanceRecord> lqw = Wrappers.lambdaQuery();
        lqw.eq(UserBalanceRecord::getUid, uid);
        lqw.eq(UserBalanceRecord::getLinkType, BalanceRecordConstants.BALANCE_RECORD_LINK_TYPE_RECHARGE);
        lqw.eq(UserBalanceRecord::getType, BalanceRecordConstants.BALANCE_RECORD_TYPE_ADD);
        lqw.orderByDesc(UserBalanceRecord::getId);
        return dao.selectList(lqw);
    }

    /**
     * 用户余额记录
     * @param uid 用户id
     * @param recordType 记录类型：all-全部，expenditure-支出，income-收入，recharge-充值
     * @param pageRequest 分页参数
     * @return PageInfo
     */
    @Override
    public PageInfo<UserBalanceRecord> getUserBalanceRecord(Integer uid, String recordType, PageParamRequest pageRequest) {
        Page<UserBalanceRecord> page = PageHelper.startPage(pageRequest.getPage(), pageRequest.getLimit());
        LambdaQueryWrapper<UserBalanceRecord> lqw = Wrappers.lambdaQuery();
        lqw.eq(UserBalanceRecord::getUid, uid);
        switch (recordType) {
            case "expenditure":
                lqw.eq(UserBalanceRecord::getType, BalanceRecordConstants.BALANCE_RECORD_TYPE_SUB);
                break;
            case "income":
                lqw.eq(UserBalanceRecord::getType, BalanceRecordConstants.BALANCE_RECORD_TYPE_ADD);
                break;
            case "recharge":
                lqw.eq(UserBalanceRecord::getType, BalanceRecordConstants.BALANCE_RECORD_TYPE_ADD);
                lqw.eq(UserBalanceRecord::getLinkType, BalanceRecordConstants.BALANCE_RECORD_LINK_TYPE_RECHARGE);
                break;
        }
        lqw.orderByDesc(UserBalanceRecord::getId);
        List<UserBalanceRecord> recordList = dao.selectList(lqw);
        return CommonPage.copyPageInfo(page, recordList);
    }

    @Override
    public BigDecimal getTodayConsumeAmount(Integer userId) {
        LocalDateTime startOfDay = LocalDate.now().atStartOfDay();
        LocalDateTime endOfDay = LocalDateTime.of(LocalDate.now(), LocalTime.MAX);
        return getConsumeAmountByDate(startOfDay, endOfDay, userId);
    }

    @Override
    public BigDecimal getWeekConsumeAmount(Integer userId) {
        LocalDateTime now = LocalDateTime.now();
        // 本周一 00:00:00
        LocalDateTime weekStart = now.with(DayOfWeek.MONDAY)
                .with(LocalTime.MIN);
        // 本周日 23:59:59
        LocalDateTime weekEnd = now.with(DayOfWeek.SUNDAY)
                .with(LocalTime.MAX);
        return getConsumeAmountByDate(weekStart, weekEnd, userId);
    }

    @Override
    public BigDecimal getMonthConsumeAmount(Integer userId) {
        LocalDateTime now = LocalDateTime.now();
        YearMonth currentMonth = YearMonth.from(now);
        LocalDateTime monthStart = currentMonth.atDay(1).atStartOfDay();
        LocalDateTime monthEnd = currentMonth.atEndOfMonth().atTime(LocalTime.MAX);
        return getConsumeAmountByDate(monthStart, monthEnd, userId);
    }

    /**
     * 获取上次svip购买记录
     * @param uid
     * @param orderNo
     * @return
     */
    @Override
    public UserBalanceRecord getPrevPaidMemberConsume(Integer uid, String orderNo) {
        LambdaQueryWrapper<UserBalanceRecord> lqw = Wrappers.lambdaQuery();
        lqw.eq(UserBalanceRecord::getUid, uid);
        lqw.eq(UserBalanceRecord::getLinkId, orderNo);
        lqw.eq(UserBalanceRecord::getLinkType, BalanceRecordConstants.BALANCE_RECORD_LINK_TYPE_SVIP);
        lqw.eq(UserBalanceRecord::getType, BalanceRecordConstants.BALANCE_RECORD_TYPE_ADD);
        lqw.orderByDesc(UserBalanceRecord::getCreateTime);
        lqw.last("limit 1");
        return getOne(lqw);
    }

    @Override
    public UserBalanceRecord getNewOrderConsume(Integer uid, Date createTime) {
        LambdaQueryWrapper<UserBalanceRecord> lqw = Wrappers.lambdaQuery();
        lqw.eq(UserBalanceRecord::getUid, uid);
        lqw.eq(UserBalanceRecord::getLinkType, BalanceRecordConstants.BALANCE_RECORD_LINK_TYPE_ORDER);
        lqw.eq(UserBalanceRecord::getType, BalanceRecordConstants.BALANCE_RECORD_TYPE_SUB);
        lqw.ge(UserBalanceRecord::getCreateTime, DateUtil.format(createTime, "yyyy-MM-dd HH:mm:ss"));
        lqw.orderByDesc(UserBalanceRecord::getCreateTime);
        lqw.last("limit 1");
        return getOne(lqw);
    }



    public BigDecimal getConsumeAmountByDate(LocalDateTime startOfDay, LocalDateTime endOfDay, Integer userId) {
        LambdaQueryWrapper<UserBalanceRecord> lqw = Wrappers.lambdaQuery();
        lqw.eq(UserBalanceRecord::getUid, userId);
        lqw
                .ge(UserBalanceRecord::getCreateTime, startOfDay)
                .le(UserBalanceRecord::getCreateTime, endOfDay);
        lqw.eq(UserBalanceRecord::getLinkType, BalanceRecordConstants.BALANCE_RECORD_LINK_TYPE_ORDER);
        lqw.eq(UserBalanceRecord::getType, BalanceRecordConstants.BALANCE_RECORD_TYPE_SUB);
        lqw.orderByDesc(UserBalanceRecord::getId);
        List<UserBalanceRecord> userBalanceRecords = dao.selectList(lqw);
        if (CollUtil.isNotEmpty(userBalanceRecords)) {
            BigDecimal reduce = userBalanceRecords.stream().map(UserBalanceRecord::getAmount)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);// 累加
            return reduce;
        }
        return BigDecimal.ZERO;
    }

    @Override
    public UserBalanceRecord getPaidMemberConsumeByDate(Integer uid, String orderNo, Date date) {
        LambdaQueryWrapper<UserBalanceRecord> lqw = Wrappers.lambdaQuery();
        lqw.eq(UserBalanceRecord::getUid, uid);
        lqw.eq(UserBalanceRecord::getLinkId, orderNo);
        lqw.eq(UserBalanceRecord::getLinkType, BalanceRecordConstants.BALANCE_RECORD_LINK_TYPE_SVIP);
        lqw.eq(UserBalanceRecord::getType, BalanceRecordConstants.BALANCE_RECORD_TYPE_ADD);
        lqw.ge(UserBalanceRecord::getCreateTime, DateUtil.format(date, "yyyy-MM-dd HH:mm:ss"));
        lqw.orderByDesc(UserBalanceRecord::getCreateTime);
        lqw.last("limit 1");
        return getOne(lqw);
    }

    @Override
    public UserBalanceRecord getPaidMemberConsumeByDate(Integer uid, String orderNo, LocalDateTime weekStart, LocalDateTime weekEnd) {
        LambdaQueryWrapper<UserBalanceRecord> lqw = Wrappers.lambdaQuery();
        lqw.eq(UserBalanceRecord::getUid, uid);
        lqw.eq(UserBalanceRecord::getLinkId, orderNo);
        lqw.eq(UserBalanceRecord::getLinkType, BalanceRecordConstants.BALANCE_RECORD_LINK_TYPE_SVIP);
        lqw.eq(UserBalanceRecord::getType, BalanceRecordConstants.BALANCE_RECORD_TYPE_ADD);
        lqw.ge(UserBalanceRecord::getCreateTime, weekStart);
        lqw.le(UserBalanceRecord::getCreateTime, weekEnd);
        lqw.orderByDesc(UserBalanceRecord::getCreateTime);
        lqw.last("limit 1");
        return getOne(lqw);
    }

    @Override
    public PageInfo<UserBalancePageDataResponse> getUserBalanceList(UserBalanceSearchRequest request, PageParamRequest pageRequest) {

        Map<String, Object> map = new HashMap<>();
        if (StrUtil.isNotBlank(request.getUserNickname())) {
            map.put("nikename", URLUtil.decode(request.getUserNickname()));
        }
        if (StrUtil.isNotBlank(request.getPhone())) {
            map.put("phone", request.getPhone());
        }
        map.put("type", BalanceRecordConstants.BALANCE_RECORD_TYPE_ADD);
        if (StrUtil.isNotBlank(request.getDateLimit())) {
            DateLimitUtilVo dateLimitVo = CrmebDateUtil.getDateLimit(request.getDateLimit());
            map.put("startTime", dateLimitVo.getStartTime());
            map.put("endTime", dateLimitVo.getEndTime());
        }
        map.put("linkType", "dividend");
        Page<UserBalanceRecord> page = PageHelper.startPage(pageRequest.getPage(), pageRequest.getLimit());
        List<UserBalancePageDataResponse> recordList = dao.findUserBalanceList(map);
        recordList.forEach(e -> e.setPhone(CrmebUtil.maskMobile(e.getPhone())));
        return CommonPage.copyPageInfo(page, recordList);
    }



}

